From: David Härdeman Date: Fri, 10 Oct 2025 07:32:33 +0000 (+0200) Subject: dhcpv6-ia: split reconf_msg struct into partial structs X-Git-Url: http://git.openwrt.org/%22https:/collectd.org//%22http:/www.crowdsec.net/%22/%22https:/collectd.org/%22http:/www.crowdsec.net/%22?a=commitdiff_plain;h=ae16476bcad27049f82e3043e88958405096c4bb;p=project%2Fodhcpd.git dhcpv6-ia: split reconf_msg struct into partial structs Change send_reconf() so that the various options are each in separate struct. This makes it easy to support a variable-length server DUID in the future. Signed-off-by: David Härdeman Link: https://github.com/openwrt/odhcpd/pull/274 Signed-off-by: Álvaro Fernández Rojas --- diff --git a/src/dhcpv6-ia.c b/src/dhcpv6-ia.c index 3d9172a..2948607 100644 --- a/src/dhcpv6-ia.c +++ b/src/dhcpv6-ia.c @@ -137,43 +137,74 @@ static size_t get_preferred_addr(const struct odhcpd_ipaddr *addrs, const size_t return m; } +enum { + IOV_HDR = 0, + IOV_SERVERID, + IOV_CLIENTID, + IOV_MESSAGE, + IOV_AUTH, + IOV_TOTAL +}; + static int send_reconf(struct dhcp_assignment *assign) { + struct interface *iface = assign->iface; + struct dhcpv6_client_header hdr = { + .msg_type = DHCPV6_MSG_RECONFIGURE, + .transaction_id = { 0, 0, 0 }, + }; struct { - struct dhcpv6_client_header hdr; - uint16_t srvid_type; - uint16_t srvid_len; - uint16_t duid_type; - uint16_t hardware_type; - uint8_t mac[6]; - uint16_t msg_type; - uint16_t msg_len; - uint8_t msg_id; - struct dhcpv6_auth_reconfigure auth; - uint16_t clid_type; - uint16_t clid_len; - uint8_t clid_data[128]; - } __attribute__((packed)) reconf_msg = { - .hdr = {DHCPV6_MSG_RECONFIGURE, {0, 0, 0}}, - .srvid_type = htons(DHCPV6_OPT_SERVERID), - .srvid_len = htons(10), - .duid_type = htons(3), - .hardware_type = htons(1), - .msg_type = htons(DHCPV6_OPT_RECONF_MSG), - .msg_len = htons(1), - .msg_id = DHCPV6_MSG_RENEW, - .auth = {htons(DHCPV6_OPT_AUTH), - htons(sizeof(reconf_msg.auth) - 4), 3, 1, 0, - {htonl(time(NULL)), htonl(++serial)}, 2, {0}}, - .clid_type = htons(DHCPV6_OPT_CLIENTID), - .clid_len = htons(assign->clid_len), - .clid_data = {0}, + uint16_t code; + uint16_t len; + uint8_t data[DUID_MAX_LEN]; + } _packed serverid = { + .code = htons(DHCPV6_OPT_SERVERID), + .len = 0, + .data = { 0 }, + }; + struct { + uint16_t code; + uint16_t len; + uint8_t data[DUID_MAX_LEN]; + } _packed clientid = { + .code = htons(DHCPV6_OPT_CLIENTID), + .len = htons(assign->clid_len), + .data = { 0 }, + }; + struct { + uint16_t code; + uint16_t len; + uint8_t id; + } _packed message = { + .code = htons(DHCPV6_OPT_RECONF_MSG), + .len = htons(1), + .id = DHCPV6_MSG_RENEW, + }; + struct dhcpv6_auth_reconfigure auth = { + .type = htons(DHCPV6_OPT_AUTH), + .len = htons(sizeof(struct dhcpv6_auth_reconfigure)), + .protocol = 3, + .algorithm = 1, + .rdm = 0, + .replay = { htonl(time(NULL)), htonl(++serial) }, + .reconf_type = 2, + .key = { 0 }, }; - struct interface *iface = assign->iface; - odhcpd_get_mac(iface, reconf_msg.mac); - memcpy(reconf_msg.clid_data, assign->clid_data, assign->clid_len); - struct iovec iov = {&reconf_msg, sizeof(reconf_msg) - 128 + assign->clid_len}; + uint8_t duid_ll_hdr[] = { 0x00, 0x03, 0x00, 0x01 }; + memcpy(serverid.data, duid_ll_hdr, sizeof(duid_ll_hdr)); + odhcpd_get_mac(iface, &serverid.data[sizeof(duid_ll_hdr)]); + serverid.len = htons(sizeof(duid_ll_hdr) + ETH_ALEN); + + memcpy(clientid.data, assign->clid_data, assign->clid_len); + + struct iovec iov[IOV_MAX] = { + [IOV_HDR] = { &hdr, sizeof(hdr) }, + [IOV_SERVERID] = { &serverid, sizeof(serverid) }, + [IOV_CLIENTID] = { &clientid, sizeof(clientid) }, + [IOV_MESSAGE] = { &message, sizeof(message) }, + [IOV_AUTH] = { &auth, sizeof(auth) }, + }; md5_ctx_t md5; uint8_t secretbytes[64]; @@ -185,8 +216,9 @@ static int send_reconf(struct dhcp_assignment *assign) md5_begin(&md5); md5_hash(secretbytes, sizeof(secretbytes), &md5); - md5_hash(iov.iov_base, iov.iov_len, &md5); - md5_end(reconf_msg.auth.key, &md5); + for (size_t i = 0; i < ARRAY_SIZE(iov); i++) + md5_hash(iov[i].iov_base, iov[i].iov_len, &md5); + md5_end(auth.key, &md5); for (size_t i = 0; i < sizeof(secretbytes); ++i) { secretbytes[i] ^= 0x36; @@ -195,10 +227,10 @@ static int send_reconf(struct dhcp_assignment *assign) md5_begin(&md5); md5_hash(secretbytes, sizeof(secretbytes), &md5); - md5_hash(reconf_msg.auth.key, 16, &md5); - md5_end(reconf_msg.auth.key, &md5); + md5_hash(auth.key, 16, &md5); + md5_end(auth.key, &md5); - return odhcpd_send(iface->dhcpv6_event.uloop.fd, &assign->peer, &iov, 1, iface); + return odhcpd_send(iface->dhcpv6_event.uloop.fd, &assign->peer, iov, ARRAY_SIZE(iov), iface); } static void dhcpv6_ia_free_assignment(struct dhcp_assignment *a)